package gui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;

import application.Gui;

/**
 * @author Miroslav Vozabal
 * Gui aimed to communicate with user of OS.
 */
public class SkyGui extends JFrame implements IGui {
	private static final long serialVersionUID = 1L;
	private JScrollPane topSP = null;
	private JScrollPane bottomSP = null;
	private JTextArea topTA = null;
	private JTextArea bottomTA = null;
	private JPanel contentJP = null;
	private JPopupMenu rightClickMenu = null;	
	private String outputText = "";	
	private Boolean inputLineBreaks = true;
	private Boolean outputLineBreaks = true;
	private JMenuItem shutdownItem;	
	private Gui gui;

		
	/**
	 * SkyGui constructor.
	 */
	public SkyGui(Gui gui) {	
		initializeComponents();
		rightMenuActions();	
		this.gui = gui;
	}		
	
	/**
	 * Gets shutdownItem.
	 * @return
	 */
	public JMenuItem getShutDownItem() {
		return shutdownItem;
	}
	
	/**
	 * Sets a focus to the bottonTA.
	 */
	private void initFocus() {
		this.addWindowFocusListener(new WindowAdapter() {
			public void windowGainedFocus (WindowEvent e) {
				bottomTA.requestFocusInWindow();
			}
		});
	}
	
	/**
	 * Provides a catching of keyStroke.
	 */
	private void catchKeyStrokes() {
		Action action = new AbstractAction() {
			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent e) {
				gui.endRead();
			}
		};

		InputMap inputMap = contentJP.getInputMap(2);
		ActionMap actionMap = contentJP.getActionMap();				
		KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_D, Event.CTRL_MASK);
		inputMap.put(key, "keyStrokeService");		
		actionMap.put("keyStrokeService", action);
	}
	
	
	/**
	 * Provides a right menu actions.
	 */
	private void rightMenuActions() {		
		rightClickMenu = new JPopupMenu();
		JMenuItem rightMenuItem1 = new JMenuItem("Clear");		
		rightClickMenu.add(rightMenuItem1);			

	
		//Click to the right menu item called clear.
		rightMenuItem1.addActionListener(new ActionListener() {			
			public void actionPerformed(ActionEvent e) {
				clearOutput();							
			}
		});
		
		//Click on the right button of mouse.
		topTA.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent arg0) {				
				if(arg0.getButton() == MouseEvent.BUTTON3) {										
					rightClickMenu.show(arg0.getComponent(), arg0.getX(), arg0.getY());
				}
			}
		});
	}
	
	/**
	 * Initializes a components.
	 */
	private void initializeComponents() {		
		contentJP = new JPanel();
		topTA = new JTextArea();
		bottomTA = new JTextArea();
		topSP = new JScrollPane(topTA);
		bottomSP = new JScrollPane(bottomTA);			
		
		//Configuration of topTA TextArea.
		topTA.setFont(new Font("Monospaced", Font.PLAIN, 20));
		topTA.setBorder(BorderFactory.createTitledBorder("Output"));
		topTA.setEditable(false);
		topTA.setLineWrap(true);
		
		//Configuration of bottomTA TextArea.
		bottomTA.setBorder(BorderFactory.createTitledBorder("Input"));
		bottomTA.setFont(new Font("Monospaced", Font.PLAIN, 20));
		bottomTA.setLineWrap(true);
		KeyHandler handler = new KeyHandler();
		bottomTA.addKeyListener(handler);		
				
		topSP.setPreferredSize(new Dimension(new Integer(500), new Integer(600)));
		bottomSP.setPreferredSize(new Dimension(new Integer(500), new Integer(100)));
		
		//Configuration of contentJP JPanel.
		contentJP.setLayout(new BoxLayout(contentJP, BoxLayout.PAGE_AXIS));				
		contentJP.add(topSP, BorderLayout.NORTH);
		contentJP.add(bottomSP, BorderLayout.SOUTH);		
	
		//Sets global layout.
		this.setLayout(new BorderLayout());
		
		//Adds tool bar.
		this.add(createToolBar(), BorderLayout.PAGE_START);
		
		//Sets configurations of this form.
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.getContentPane().add(contentJP);		
		this.setSize(500, 600);
		this.setVisible(true);
		this.setLocationRelativeTo(null);
		this.setTitle("SkyOS");
		
		initFocus();
		//catch KeyStrokes
		catchKeyStrokes();
		
	}
	
	 
	/**
	 * @author Miroslav Vozabal
	 * Catches events from keyboard and services them.
	 */
	private class KeyHandler extends KeyAdapter{
		public void keyReleased(KeyEvent e)
		 {
		     int key=e.getKeyCode();
		     if(e.getSource()==bottomTA)
		     {
		         if(key==KeyEvent.VK_ENTER)
		         { 
		             writeOutput(bottomTA.getText());
		             gui.write(bottomTA.getText());
		             bottomTA.setText("");
		         }
		         if(key == KeyEvent.VK_UP){
	        		 gui.previouslyCommand();
		        	
		         }
		         if(key == KeyEvent.VK_DOWN){
		        	gui.nextCommand();
		         }
		     }
		 }
	}
	
	/**
	 * Writes the string to the output panel and seperate it from the previous string with inserting of new line.
	 * @param output
	 */
	public void writeOutputLn(String output) {
		String temp;
		outputText = topTA.getText();
		temp = outputText + output + "\n";
		topTA.setText(temp);
	}
	
	/**
	 * Writes the string to the output panel after the position of the last previous string.
	 * @param output
	 */
	public void writeOutput(String output) {
		String temp;
		outputText = topTA.getText();
		temp = outputText + output;
		topTA.setText(temp);
	}
	
	
	/**
	 * Writes the string to the input panel after the position of the last previous string.
	 * @param input
	 */
	public void writeInput(String input)
	{
		bottomTA.setText(input);
	}
		
	/**
	 * Clears the text in the output panel.
	 */
	public void clearOutput() {
		topTA.setText("");
	}
	
	/**
	 * Clears the text in the input panel.
	 */
	public void clearInutput() {
		bottomTA.setText("");		
	}
	
	/**
	 * Creates main form menu.
	 * @return JMenuBar
	 */
	private JMenuBar createToolBar() {
		JMenuBar menuBar = new JMenuBar();		
		JMenu menu1 = new JMenu("OS");
		JMenu menu2 = new JMenu("Input");
		JMenu menu3 = new JMenu("Output");		
		JMenuItem menu1Item1 = new JMenuItem("Shutdown");	
		JMenuItem menu2Item1 = new JMenuItem("Line breaks");
		JMenuItem menu2Item2 = new JMenuItem("Font size");			
		JMenuItem menu3Item1 = new JMenuItem("Line breaks");
		JMenuItem menu3Item2 = new JMenuItem("Font size");
		
		//Connect components to menu1
		menuBar.add(menu1);
		menu1.add(menu1Item1);
		
		shutdownItem = menu1Item1;
		
		//Connect components to  menu2
		menuBar.add(menu2);
		menu2.add(menu2Item1);
		menu2.add(menu2Item2);
		
		//Connect components to  menu3
		menuBar.add(menu3);
		menu3.add(menu3Item1);
		menu3.add(menu3Item2);
		
	
		//Click on the button of font size in the menu called Input.
		menu2Item2.addActionListener(new ActionListener() {			
			public void actionPerformed(ActionEvent e) {
				new FontControl(bottomTA);
			}
		});
		
		//Click on the button of font size in the menu called Output.
		menu3Item2.addActionListener(new ActionListener() {			
			public void actionPerformed(ActionEvent e) {
				new FontControl(topTA);				
			}
		});
		
		//Click on the button of breaking lines in the menu called Input.
		menu2Item1.addActionListener(new ActionListener() {			
			public void actionPerformed(ActionEvent e) {
				if (inputLineBreaks == true) {
					bottomTA.setLineWrap(false);
					inputLineBreaks = false;				
				}
				else {
					bottomTA.setLineWrap(true);
					inputLineBreaks = true;
				}				
			}
		});
			
		//Click on the button of breaking lines in the menu called Output.
		menu3Item1.addActionListener(new ActionListener() {			
			public void actionPerformed(ActionEvent e) {
				if (outputLineBreaks == true) {
					topTA.setLineWrap(false);
					outputLineBreaks = false;					
				}
				else {
					topTA.setLineWrap(true);
					outputLineBreaks = true;
				}				
			}
		});		
		return  menuBar;
	}	
}
